import re
import math

from odoo import fields, models, api, _
from odoo.exceptions import ValidationError
from odoo.tools import float_compare


class PresetsBom(models.Model):
    _name = 'sb.presets.bom'
    _inherit = ['portal.mixin', 'mail.thread.main.attachment', 'mail.activity.mixin']
    _order = 'id desc'
    _description = '预设BOM'

    name = fields.Char(string="Name", default="New", compute='_compute_name', store=True)
    product_id = fields.Many2one('product.product', string="MPN", domain=[('is_finished', '=', True)], tracking=True)
    bom_line_ids = fields.One2many('sb.presets.bom.line', 'presets_bom_id', string="物料清单明细行")
    state = fields.Selection([
        ('draft', 'Draft'),
        ('wait_approval', 'Waiting for Approval'),
        ('approved', 'Approved'),
        # ('done', 'Done')
    ], string="状态", default='draft', tracking=True)
    # 拼版
    sheet_type = fields.Selection([
        ('sheetA', 'sheetA'),
        ('sheetB', 'sheetB')
    ], default='sheetA', string="拼版", tracking=True, required=True)
    # 多拼版
    sheet_multi = fields.Boolean('多拼版', tracking=True)
    presets_diff_id = fields.Many2one('sb.presets.bom.diff', string='差异', compute='_compute_presets_diff_id')
    pnl_width = fields.Float('PNL 经向', tracking=True)
    pnl_length = fields.Float('PNL 纬向', tracking=True)
    pnl = fields.Float('PNL/SHEET', tracking=True)
    set_pnl = fields.Float('SET/PNL', tracking=True)

    pcs_set = fields.Float('PCS/SET', tracking=True)
    # 铜厚
    thickness = fields.Float('外层完成铜厚', tracking=True)
    # 联系人/电话
    contact = fields.Char('联系人/电话')

    remark = fields.Text('Remark')

    sheet_radial = fields.Float('sheet radial', tracking=True)
    sheet_zonal = fields.Float('sheet zonal', tracking=True)

    attachment_ids = fields.One2many('ir.attachment', 'res_id', domain=[('res_model', '=', 'sb.presets.bom')],
                                     string='Attachments')

    @api.depends('product_id.name')
    def _compute_name(self):
        for record in self:
            record.name = record.product_id.name

    @api.depends('product_id')
    def _compute_presets_diff_id(self):
        for record in self:
            record.presets_diff_id = self.env['sb.presets.bom.diff'].search([('presets_bom_id', '=', record.id)],
                                                                            limit=1)

    def action_presets_diff_id(self):
        self.ensure_one()
        return {
            'type': 'ir.actions.act_window',
            'name': '差异表',
            'res_model': 'sb.presets.bom.diff',
            'view_mode': 'form',
            'res_id': self.presets_diff_id.id,
            'target': 'current',
        }


class PresetsBomLine(models.Model):
    _name = 'sb.presets.bom.line'
    _inherit = ['portal.mixin', 'mail.thread.main.attachment', 'mail.activity.mixin']
    _description = '预设BOM行'

    presets_bom_id = fields.Many2one('sb.presets.bom', string="预设BOM", ondelete='cascade')
    product_id = fields.Many2one('product.product', string="产品", tracking=True)
    categ_id = fields.Many2one('product.category', string="产品类别", related="product_id.categ_id", store=True)
    default_code = fields.Char(string="默认编码", related="product_id.default_code", store=True)
    product_length = fields.Float('product length(M)', tracking=True)
    product_qty = fields.Integer(string="PANEL 用量(张)", tracking=True)  # 每叠构中需求的数量
    product_uom_id = fields.Many2one('uom.uom', string="Product Uom")

    product_stock_qty = fields.Float('dosage', digits=(10, 6))

    @api.onchange('product_id')
    def _onchange_product_id(self):
        for record in self:
            if record.product_id.categ_id.code in ['FOBR', 'FOCF']:
                u = self.env['uom.uom'].search([('code', '=', 'zhang')], limit=1) or record.product_id.uom_id
                record.product_uom_id = u
            else:
                record.product_uom_id = record.product_id.uom_id
            # record.product_uom_id = record.product_id.uom_id
            if record.product_id.categ_id.parent_id.code and record.product_id.categ_id.parent_id.code == 'FO':
                match = re.search(r'_([0-9]+)um', record.product_id.name)
                if match:
                    self.product_length = match.group(1)

    def compute_product_qty(self, order_qty):
        self.ensure_one()
        if not self.product_id or not order_qty:
            return 0
        product_stock_qty = 0
        if self.product_id.categ_id.code in ('BS', 'DF') or self.product_id.categ_id.parent_id.code in ('BS', 'DF'):
            bom_id = self.presets_bom_id
            sheet_qty = math.floor(bom_id.sheet_radial / bom_id.pnl_width)
            # 不是A/B拼版
            if not bom_id.sheet_multi:
                denominator = bom_id.pcs_set * bom_id.set_pnl * bom_id.pnl
                if denominator:
                    length = (1.03 * order_qty * (bom_id.pnl_width + 2) * sheet_qty * self.product_qty) / denominator
                    length = length / 1000
                    roll = length / self.product_length if self.product_length else 0
                    product_stock_qty = self.product_id.uom_po_id._compute_quantity(roll, self.product_id.uom_id)
            # A/B拼版
            else:
                if not bom_id.child_ids:
                    return 0
                b_bom_id = bom_id.child_ids[0]
                denominator = (bom_id.pcs_set * bom_id.set_pnl * bom_id.pnl) + (
                            b_bom_id.pcs_set * b_bom_id.set_pnl * b_bom_id.pnl)
                if bom_id.pnl_width == b_bom_id.pnl_width:
                    if denominator:
                        length = (1.03 * order_qty * (
                                    bom_id.pnl_width + 2) * sheet_qty * self.product_qty) / denominator
                        length = length / 1000
                        roll = length / self.product_length if self.product_length else 0
                        product_stock_qty = self.product_id.uom_po_id._compute_quantity(roll, self.product_id.uom_id)
                else:
                    sheet_qty = math.floor(bom_id.sheet_zonal / bom_id.pnl_length)
                    a_pnl_qty = bom_id.pnl / sheet_qty
                    b_pnl_qty = b_bom_id.pnl / sheet_qty
                    if denominator:
                        length = (1.03 * order_qty * (((bom_id.pnl_width + 2) * a_pnl_qty) + (
                                    (b_bom_id.pnl_width + 2) * b_pnl_qty)) * self.product_qty) / denominator
                        length = length / 1000
                        roll = length / self.product_length if self.product_length else 0
                        product_stock_qty = self.product_id.uom_po_id._compute_quantity(roll, self.product_id.uom_id)

        return product_stock_qty
